﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;

namespace API.Models.Repository
{
    public class Sessions_RepositoryAsync : GenericRepositoryAsync<PartnerDbContext, SEC_SESSIONS>
    {
        public async Task<SEC_SESSIONS> GetSession(string api_key, string ip)
        {
            var data = await this.Find(r => 
                r.APIKEY == api_key 
                && r.IP == ip
                && !r.LOGOFF_DATETIME.HasValue);

            if (!data.Any())
                throw new Exception("Сессия с указанным api_key не найдена");

            return data.SingleOrDefault();
        }

        public async Task<SEC_SESSIONS> LogIn(string email, string password, string ip)
        {
            if (String.IsNullOrEmpty(email))
                throw new Exception("Не указан email");

            if (String.IsNullOrEmpty(password))
                throw new Exception("Не указан пароль");

            var password_hash = API.Core.Util.GetMD5(password);
            var api_key = API.Core.Util.GetMD5(Guid.NewGuid().ToString());

            var user = _entities.SEC_USERS.SingleOrDefault(r =>
                r.EMAIL == email &&
                r.PASSWORD_HASH == password_hash);

            if (user == null)
                throw new Exception("Пользователь не найден");

            /// TODO
            /// Переделать это кусок!
            /// Нужно использовать доступ через репозитоии
            var allow_companies = _entities.SEC_USER_COMPANIES
                .Where(r =>
                    r.USER_GUID == user.GUID_RECORD &&
                    r.IS_ALLOWED)
                .ToList();

            var last_session = _entities.SEC_SESSIONS
                .Where(r => r.USER_GUID == user.GUID_RECORD)
                .OrderByDescending(r => r.LOGON_DATETIME)
                .FirstOrDefault();

            var COMPANY_GUID = Guid.Empty;

            if (last_session != null)
                if (allow_companies.Any(r => r.COMPANY_GUID == last_session.COMPANY_GUID))
                    COMPANY_GUID = last_session.COMPANY_GUID; //.GetValueOrDefault();

            var session = new SEC_SESSIONS
            {
                GUID_RECORD = Guid.NewGuid(),
                USER_GUID = user.GUID_RECORD,
                COMPANY_GUID = COMPANY_GUID,
                LOGON_DATETIME = DateTime.Now,
                IP = ip,
                APIKEY = api_key
            };

            await this.Add(session);
            await this.Save();

            return await this.GetSession(api_key, ip);
        }

        public async Task<SEC_SESSIONS> LogIn(string api_key, string ip)
        {
            return await this.GetSession(api_key, ip);
        }

        public async Task LogOut(string api_key, string ip)
        {
            var session = await this.GetSession(api_key, ip);
            session.LOGOFF_DATETIME = DateTime.Now;

            await this.Edit(session);
            await this.Save();
        }

        public async Task<SEC_USERS> GetUser(string api_key, string ip)
        {
            var _userRepository = new Users_RepositoryAsync();

            var _session = await this.GetSession(api_key, ip);
            var user = await _userRepository.Find(r => r.GUID_RECORD == _session.USER_GUID);

            return user.SingleOrDefault();
        }

        public async Task<WH_COMPANIES> GetCompany(string api_key, string ip)
        {
            var _companyRepository = new Companies_RepositoryAsync();

            var _session = await this.GetSession(api_key, ip);
            var company = await _companyRepository.Find(r => r.GUID_RECORD == _session.COMPANY_GUID);

            return company.SingleOrDefault();
        }

        public async Task<IEnumerable<WH_COMPANIES>> GetAllowedCompanies(string api_key, string ip)
        {
            var _session = await this.GetSession(api_key, ip);
            var _userCompaniesRepository = new UserCompanies_RepositoryAsync();

            var data = await _userCompaniesRepository.Find(new[] {"COMPANY"}, r => r.USER_GUID == _session.USER_GUID && r.IS_ALLOWED);
            var companies = data.Select(r => r.COMPANY);

            return companies;
        }

        public async Task ChangeCompany(string api_key, string ip, Guid COMPANY_GUID)
        {
            var _session = await this.GetSession(api_key, ip);
            _session.COMPANY_GUID = COMPANY_GUID;

            await this.Edit(_session);
            await this.Save();
        }
    }
}